package com.info.zhiduoduo.weixin.service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.Condition;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.info.zhiduoduo.common.configs.ForeignConfig;
import com.info.zhiduoduo.common.configs.YunKongConfig;
import com.info.zhiduoduo.common.configs.ZddUrlConfig;
import com.info.zhiduoduo.common.constants.Constants;
import com.info.zhiduoduo.common.constants.SmartResult;
import com.info.zhiduoduo.common.constants.StatusMsg;
import com.info.zhiduoduo.common.constants.crowdsource.CrowdsourceRegfromType;
import com.info.zhiduoduo.common.constants.crowdsource.CrowdsourceUserType;
import com.info.zhiduoduo.common.exception.Asserts;
import com.info.zhiduoduo.common.exception.SmartException;
import com.info.zhiduoduo.common.formbean.BaseSimpleFormBean;
import com.info.zhiduoduo.common.utils.LogUtil;
import com.info.zhiduoduo.common.utils.NumberUtil;
import com.info.zhiduoduo.common.utils.RandomUtil;
import com.info.zhiduoduo.common.utils.StringUtil;
import com.info.zhiduoduo.core.service.CommonService;
import com.info.zhiduoduo.core.service.WxCrowdsourceMessageService;
import com.info.zhiduoduo.core.service.common.BaseService;
import com.info.zhiduoduo.core.service.common.DocService;
import com.info.zhiduoduo.core.service.impl.BankCardElementCertificationService;
import com.info.zhiduoduo.repository.dto.crowdsource.CrowdsourceInfoDto;
import com.info.zhiduoduo.repository.dto.crowdsource.CrowdsourceProjectItemDetailDto;
import com.info.zhiduoduo.repository.dto.crowdsource.ExportProjectAcceptanceDto;
import com.info.zhiduoduo.repository.dto.crowdsource.ExportProjectAcceptanceItemDto;
import com.info.zhiduoduo.repository.entity.company.Company;
import com.info.zhiduoduo.repository.entity.crowdsource.*;
import com.info.zhiduoduo.repository.mapper.crowdsource.CrowdsourceAccountMapper;
import com.info.zhiduoduo.repository.mapper.crowdsource.CrowdsourceFileMapper;
import com.info.zhiduoduo.repository.mapper.crowdsource.CrowdsourceProjectItemMapper;
import com.info.zhiduoduo.repository.mapper.crowdsource.CrowdsourceProjectMapper;
import com.info.zhiduoduo.weixin.formbean.crowdsource.*;

import com.info.zhiduoduo.weixin.formbean.project.GenerateProjectAcceptance;
import com.info.zhiduoduo.weixin.formbean.project.UploadProjectFileUrlFormBean;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class CrowdsourceService extends BaseService {

	@Resource
	CrowdsourceAccountMapper crowdsourceAccountMapper;
	@Resource
	CrowdsourceProjectMapper crowdsourceProjectMapper;
	@Resource
	CrowdsourceProjectItemMapper crowdsourceProjectItemMapper;
	@Autowired
	WxCrowdsourceMessageService wxCrowdsourceMessageService;
	@Autowired
	CommonService commonService;
	@Autowired
	ZddUrlConfig zddUrlConfig;
	@Resource
	DocService docService;

	@Resource
	CrowdsourceFileMapper crowdsourceFileMapper;

	@Autowired
	BankCardElementCertificationService bankCardElementCertificationService;

	public SmartResult registerCrowdsource(BaseSimpleFormBean<RegCrowdsourceFormBean> formBean) {

		SmartResult smartResult = new SmartResult();

		RegCrowdsourceFormBean reqdata = formBean.getReqdata();

		if (null == reqdata || StringUtil.isEmpty(reqdata.getPhone()) || StringUtil.isEmpty(reqdata.getVerifycode()) ||
				formBean.getUserid() == 0) {
			smartResult.setStateMsg(StatusMsg.StatusMsg_101);
			return smartResult;
		}

		int crowdsourceid = formBean.getUserid();

		String phone = reqdata.getPhone();
		commonService.checkPhoneVerifyCode(phone, reqdata.getVerifycode());

		Crowdsource crowdsource = new Crowdsource().selectById(crowdsourceid);
		//2020-09-24   手机端注册如果后台有企业了要直接绑定上去
		List<Crowdsource> crowdsourceList = new Crowdsource().selectList(Condition.create().eq("phone", phone));
		if (!CollectionUtils.isEmpty(crowdsourceList)) {
			if (crowdsourceList.size() != 1) {
				return smartResult(StatusMsg.StatusMsg_622);
			}
			//判断 之前注册的数据是否有openid
			if (StringUtil.isEmpty(crowdsourceList.get(0).getOpenid())) {
				//把从微信端生成的crowdsource中的openid和微信头像信息更新到老数据上
				crowdsourceList.get(0)
						.setOpenid(crowdsource.getOpenid())
						.setRegfrom(CrowdsourceRegfromType.WEICHAT)
						.setAvatar(crowdsource.getAvatar())
						.setNickname(crowdsource.getNickname())
						.setSex(crowdsource.getSex());
				if (!crowdsourceList.get(0).updateById()) {
					return smartResult(StatusMsg.StatusMsg_199);
				} else {
					//然后干掉微信端生成的crowsource数据
					crowdsource.deleteById();
					return smartResult(crowdsourceList.get(0).getCrowdsourceid());
				}
			}
		} else {
			if (null == crowdsource) {
				smartResult.setStateMsg(StatusMsg.StatusMsg_601);
				return smartResult;
			} else if (crowdsource.getState() >= Constants.user_state_2) {
				smartResult.setStateMsg(StatusMsg.StatusMsg_604);
				return smartResult;
			}

			//更新用户手机号
			crowdsource.setPhone(phone);
			crowdsource.setState(Constants.crowdsource_state_2);
			if (crowdsource.updateById()) {
				//注册成功，创建创客账户
				new CrowdsourceAccount().setCrowdsourceid(crowdsourceid).setRealnameAuth(Constants.crowdsource_auth_1).insert();
			}
		}

		return smartResult();
	}

	public SmartResult realnameAuth(BaseSimpleFormBean<CrowdsourceRealNameAuthFormBean> formBean) {
		if (null == formBean || null == formBean.getReqdata() || 0 == formBean.getUserid()) {
			return errorParamSmartResult();
		}
		CrowdsourceRealNameAuthFormBean reqdata = formBean.getReqdata();
		//获取自然人信息
		int crowdsourceid = formBean.getUserid();
		Crowdsource crowdsource = new Crowdsource().selectById(crowdsourceid);
		if (null == crowdsource) {
			return smartResult(StatusMsg.StatusMsg_601);
		}
		//获取绑定的公司信息
		Company company = new Company().selectById(reqdata.getBindcompid());
		if (null == company) {
			return smartResult(StatusMsg.StatusMsg_302);
		}
		//保存自然人身份证图片
		if (StringUtil.isNotEmpty(reqdata.getIdfrontimg())) {
			saveCrowdsourceFile(crowdsourceid,reqdata.getIdfrontimg(),1);
		}
		if (StringUtil.isNotEmpty(reqdata.getIdbackimg())) {
			saveCrowdsourceFile(crowdsourceid,reqdata.getIdbackimg(),2);
		}
		//获取自然人实名认证信息
		CrowdsourceAccount crowdsourceAccount = new CrowdsourceAccount().selectOne(Condition.create().eq("crowdsourceid", crowdsourceid));
		//判断是新增还是修改
		if (null == crowdsourceAccount) {
			//判断身份证有没有注册过
			/*int count = new CrowdsourceAccount().selectCount(Condition.create().eq("idno", reqdata.getIdno()));
			Asserts.equalZero(count, StatusMsg.StatusMsg_611);*/

			CrowdsourceAccount crowdsourceAccount2 = new CrowdsourceAccount().selectOne(Condition.create().eq("idno", reqdata.getIdno()));
			if(  crowdsourceAccount2 != null && crowdsourceAccount2.getCrowdsourceid() != null ){
				// 需要进一步判断 是否是 补录人员   并进行数据处理
				int id = crowdsourceRepairData(crowdsource, crowdsourceAccount2);
				if( id > 0 ) return smartResult(id);
				return smartResult(StatusMsg.StatusMsg_611);
			}

			// 同一身份证不能同时注册自然人和创客
			/*int makerCount = new MakerAccount().selectCount(
					Condition.create().eq("idno", reqdata.getIdno()).ge("realname_auth", Constants.realname_auth_2));
			Asserts.equalZero(makerCount, StatusMsg.StatusMsg_225);*/

			if (StringUtil.isAnyEmpty(reqdata.getAcctno(), reqdata.getRealname(), reqdata.getIdno())) {
					return errorParamSmartResult();
			}
			return commonSave(crowdsourceid, crowdsource, reqdata, "", "");
		} else {
			//判断身份证有没有修改，如果修改了，判断修改后的身份证有没有注册
			if (!reqdata.getIdno().equals(crowdsourceAccount.getIdno())) {
				//如果新身份证号跟之前提交的不同，那么判断新身份证是否已经注册了。
				//todo 需要判断是否是补录人员注册

				CrowdsourceAccount crowdsourceAccount2 = new CrowdsourceAccount().selectOne(Condition.create().eq("idno", reqdata.getIdno()));
				if(  crowdsourceAccount2 != null && crowdsourceAccount2.getCrowdsourceid() != null ){
					// 需要进一步判断 是否是 补录人员   并进行数据处理
					int id = crowdsourceRepairData(crowdsource, crowdsourceAccount2);
					if( id > 0 ){
						// 修改账户信息
						BeanUtils.copyProperties(reqdata, crowdsourceAccount2);
						crowdsourceAccount2.setRealnameAuth(Constants.crowdsource_auth_3);
						if (!crowdsourceAccount2.updateById()) {
							return smartResult(StatusMsg.StatusMsg_199);
						}
						return smartResult(id);
					}
					return smartResult(StatusMsg.StatusMsg_611);
				}

				/*int count = new CrowdsourceAccount().selectCount(Condition.create().eq("idno", reqdata.getIdno()));
				if (count > 0) {
					return smartResult(StatusMsg.StatusMsg_611);
				}*/
			}

			if (StringUtil.isAnyEmpty(reqdata.getAcctno(), reqdata.getRealname(), reqdata.getIdno())) {
				return errorParamSmartResult();
			}
			return commonUpdate(reqdata, crowdsourceAccount, "", "");
		}
	}


	/**
	 * 对众包自然人数据 进行修复
	 * @param crowdsource 微信端注册（实名信息）
	 * @param crowdsourceAccount  根据身份证 查询的
	 */
	private int  crowdsourceRepairData(Crowdsource crowdsource , CrowdsourceAccount crowdsourceAccount){
		Integer crowdsourceId = crowdsourceAccount.getCrowdsourceid();
		// 表示一致(这种情况不会发生)
		if( crowdsource.getCrowdsourceid() == (int)crowdsourceId  ) return 0;
		// 获取 自然人信息
		Crowdsource crowdsource2 = new Crowdsource().selectById(crowdsourceId);
		if( crowdsource2 == null ) return 0;  //绑定 自然人 混乱
		// 表示 当前是 补录信息
		if( crowdsource2.getRegfrom() == 3 ) {
			// 将实名认证的 信息 填充到 补录创建信息中
			int id = crowdsource2.getCrowdsourceid();
			BeanUtils.copyProperties( crowdsource , crowdsource2 );
			crowdsource2.setCrowdsourceid(id);
			// 修改 信息
			if( crowdsource2.updateById() ){
				// 删除 注册账号数据
				new CrowdsourceAccount().delete(Condition.create().eq("crowdsourceid", crowdsource.getCrowdsourceid()));
				crowdsource.deleteById(); // 删除 注册信息
				return id;
			}
			return 0;
		}else {
			// 不是 补录信息 不进行处理
			// 返回错误
			return 0;
		}
	}





	private void saveCrowdsourceFile(int userid,String path,int type){
		crowdsourceFileMapper.delFileByIdAndType(userid,type);
		CrowdsourceFile crowdsourceFile = new CrowdsourceFile();
		crowdsourceFile.setFilePath(path);
		crowdsourceFile.setCrowdsourceid(userid);
		crowdsourceFile.setFileType(type);
		crowdsourceFile.insert();
	}

	/**
	 * 自然人修改
	 *
	 * @param reqdata
	 * @param crowdsourceAccount
	 * @param naturalNumber
	 * @return
	 */
	private SmartResult commonUpdate(CrowdsourceRealNameAuthFormBean reqdata, CrowdsourceAccount crowdsourceAccount, String naturalNumber,
	                                 String yunkongId) {
		BeanUtils.copyProperties(reqdata, crowdsourceAccount);
		crowdsourceAccount.setRealnameAuth(Constants.crowdsource_auth_3);
		if (StringUtil.isNotEmpty(naturalNumber) && StringUtil.isNotEmpty(yunkongId)) {
			crowdsourceAccount.setNaturalNumber(naturalNumber).setYunkongId(yunkongId).setYunkongAcctno(reqdata.getAcctno());
		}
		if (!crowdsourceAccount.updateById()) {
			return smartResult(StatusMsg.StatusMsg_199);
		} else {
			return smartResult();
		}
	}

	/**
	 * 新增自然人
	 *
	 * @param crowdsourceid
	 * @param crowdsource
	 * @param reqdata
	 * @param naturalNumber
	 * @return
	 */
	private SmartResult commonSave(int crowdsourceid, Crowdsource crowdsource, CrowdsourceRealNameAuthFormBean reqdata,
	                               String naturalNumber, String yunKongId) {
		CrowdsourceAccount crowdsourceAccount = new CrowdsourceAccount().setCrowdsourceid(crowdsourceid)
				.setRealnameAuth(Constants.crowdsource_auth_3);
		BeanUtils.copyProperties(reqdata, crowdsourceAccount);
		if (StringUtil.isNotEmpty(naturalNumber) && StringUtil.isNotEmpty(yunKongId)) {
			crowdsourceAccount.setNaturalNumber(naturalNumber).setYunkongId(yunKongId).setYunkongAcctno(reqdata.getAcctno());
		}
		if (crowdsourceAccount.insert()) {
			wxCrowdsourceMessageService.registerSucceed(reqdata.getRealname(), crowdsource.getOpenid(),crowdsourceAccount.getCrowdsourceid());
			return smartResult();
		} else {
			return smartResult(StatusMsg.StatusMsg_199);
		}
	}

	public SmartResult getCrowdsourceInfo(BaseSimpleFormBean formBean) {
		int crowdsourceid = formBean.getUserid();
		CrowdsourceInfoDto info = crowdsourceAccountMapper.getInfo(crowdsourceid);
		return smartResult(info);
	}

	public SmartResult acceptProtocolAndAuth(BaseSimpleFormBean formBean) {
		Integer id = formBean.getUserid();
		CrowdsourceAccount crowdsourceAccount = new CrowdsourceAccount().selectOne(Condition.create().eq("crowdsourceid", id));
		if (crowdsourceAccount == null) return smartResult(StatusMsg.StatusMsg_601);

		if (crowdsourceAccount.getRealnameAuth() == Constants.crowdsource_auth_3) {
			return smartResult(StatusMsg.StatusMsg_603);
		}

		String contractNo = RandomUtil.createRandomNo("CROWD_", "");
		boolean update = crowdsourceAccount.setContractNo(contractNo).setRealnameAuth(Constants.crowdsource_auth_3).updateById();

		if (update) return smartResult();
		else return optFailSmartResult();
	}

	public SmartResult getProjectList(BaseSimpleFormBean formBean) {
		int crowdsourceid = formBean.getUserid();
		// 4:自然人 6:智众包创客
		int idtype = formBean.getIdtype();
		int crowdsourceUserType = idtype == 4 ? CrowdsourceUserType.NATURAL_PERSON : CrowdsourceUserType.STUDIO;
		Page<Object> page = PageHelper.startPage(formBean.getPage(), formBean.getRows());
		crowdsourceProjectItemMapper.getItemListByUserid(crowdsourceid, crowdsourceUserType);
		return smartResultPage(page);
	}

	public SmartResult getProjectDetail(BaseSimpleFormBean<Integer> formBean) {
		Integer projectItemId = formBean.getReqdata();
		CrowdsourceProjectItemDetailDto itemDetailDto = crowdsourceProjectItemMapper.getItemDetailDto(projectItemId);
		return smartResult(itemDetailDto);
	}

	/**
	 * 更新银行卡信息
	 * @param formBean
	 * @return
	 */
	public SmartResult updateBankInfo(BaseSimpleFormBean<UpdateBankInfoFormBean> formBean){
		if (null == formBean.getReqdata() || 0 == formBean.getUserid()
				|| StringUtil.isEmpty(formBean.getReqdata().getAcctno()) || StringUtil.isEmpty(formBean.getReqdata().getBankName())
				|| StringUtil.isEmpty(formBean.getReqdata().getOpenAcctBankName())){
			return smartResult(StatusMsg.StatusMsg_101);
		}
		UpdateBankInfoFormBean reqdata = formBean.getReqdata();

		JSONObject jsonObject = bankCardElementCertificationService.homeQuery(reqdata.getAcctno());
		if (!BankCardElementCertificationService.TYPE.equals(jsonObject.getString("type"))){
			return smartResult(StatusMsg.BANKCARD_TYPE);
		}
		int crowdsourceid = formBean.getUserid();
		Crowdsource crowdsource = new Crowdsource().selectById(crowdsourceid);
		CrowdsourceAccount crowdsourceAccount = new CrowdsourceAccount().selectOne(Condition.create().eq("crowdsourceid", crowdsourceid));
		if (null == crowdsource || null == crowdsourceAccount){
			return smartResult(StatusMsg.StatusMsg_601);
		}
		if (org.apache.commons.lang3.StringUtils.isNotBlank(reqdata.getAlipayAccount())){
			crowdsourceAccount.setAlipayLogonId(reqdata.getAlipayAccount());
		}
		if (null != reqdata.getPaymentAccountStatus()){
			crowdsourceAccount.setPaymentAccountStatus(reqdata.getPaymentAccountStatus());
		}
		crowdsourceAccount.setAcctno(reqdata.getAcctno())
						  .setBankname(reqdata.getBankName())
						  .setOpenAcctBankName(reqdata.getOpenAcctBankName())
				.setCardName(jsonObject.getString("cardName"))
				.setBankProvince(jsonObject.getString("province"))
				.setBankCity(jsonObject.getString("city")).updateById();
		return smartResult();
	}

	public SmartResult updateEmergencyContact(BaseSimpleFormBean<UpdateEmergencyContactFormBean> formBean) {
		UpdateEmergencyContactFormBean temp = formBean.getReqdata();
		CrowdsourceAccount update = new CrowdsourceAccount();
		BeanUtils.copyProperties(temp,update);
		update.updateById();
		return smartResult();
	}
	/**
	 * 上传众包任务证据链
	 *
	 * @param formBean formBean
	 * @return success
	 */
	@Transactional
	public SmartResult uploadProjectFileUrl(BaseSimpleFormBean<UploadProjectFileUrlFormBean> formBean) {
		if (null == formBean || null == formBean.getReqdata() || CollectionUtils.isEmpty(formBean.getReqdata().getProjectIds())) {
			return errorParamSmartResult();
		}
		UploadProjectFileUrlFormBean reqdata = formBean.getReqdata();
		List<CrowdsourceProject> crowdsourceProjectList = new CrowdsourceProject().selectList(Condition.create().in("projectid", reqdata.getProjectIds()));
		if (CollectionUtils.isEmpty(crowdsourceProjectList)) {
			return smartResult(StatusMsg.StatusMsg_606);
		}
		for(CrowdsourceProject crowdsourceProject:crowdsourceProjectList) {
			crowdsourceProject.setProjectFileUrl(reqdata.getProjectFileUrl());
			//保存备注
			crowdsourceProject.setRemarksField(reqdata.getRemarksField());
			if (!crowdsourceProject.updateById()) {
				throw new SmartException(StatusMsg.StatusMsg_199);
			}
		}
		return smartResult();
	}

	/**
	 * 针对已验收的项目生成为交付物
	 * @param compid
	 * @return
	 */
	public SmartResult generateProjectDeliveryFile(int compid,GenerateProjectAcceptance acceptance){
		Company company = new Company().selectById(compid);
		Asserts.notNull(company, StatusMsg.StatusMsg_302);

		Asserts.notNull(NumberUtil.intIn(acceptance.getTemplateType(), 2, 3));
		List<ExportProjectAcceptanceDto> dtos = docService.generateCrowdsourceDocDeliverFile(compid, acceptance.getProjectIds(), acceptance.getTemplateType(), true);
		Set<String> projectIds = dtos.stream().map(t->t.getProjectid().toString()).collect(Collectors.toSet());

		if(StringUtils.isNotBlank(acceptance.getProjectIds())) {
			if(CollectionUtils.isEmpty(dtos)){
				return SmartResult.fail(StatusMsg.StatusMsg_142);
			}
			String[] originalIds = acceptance.getProjectIds().split(",");
			if (projectIds.size() != originalIds.length) {
				Set<String> originalList = new HashSet<>(Arrays.asList(originalIds));
				originalList.removeAll(projectIds);
				return SmartResult.success(originalList);
			}
		}
		return SmartResult.success();
	}
	@Transactional
	public SmartResult subprojectEvidenceChain(BaseSimpleFormBean<UploadProjectFileUrlFormBean> formBean) {
		if (null == formBean || null == formBean.getReqdata() || CollectionUtils.isEmpty(formBean.getReqdata().getProjectIds())) {
			return errorParamSmartResult();
		}
		UploadProjectFileUrlFormBean reqdata = formBean.getReqdata();
		List<CrowdsourceProjectItem> crowdsourceProjectItems = new CrowdsourceProjectItem().selectList(Condition.create().in("projectid", reqdata.getProjectIds()));
		if (CollectionUtils.isEmpty(crowdsourceProjectItems)) {
			return smartResult(StatusMsg.StatusMsg_606);
		}
		for(CrowdsourceProjectItem crowdsourceProjectItem:crowdsourceProjectItems) {
			crowdsourceProjectItem.setProjectFileUrl(reqdata.getProjectFileUrl());
			if (!crowdsourceProjectItem.updateById()) {
				throw new SmartException(StatusMsg.StatusMsg_199);
			}
		}
		return smartResult();
	}
}
